import { DeleteOutlined } from "@ant-design/icons"
import { Button, Divider, Input, Upload, notification } from "antd"
import { UploadChangeParam } from "antd/es/upload/interface"
import { UploadFile } from "antd/lib/upload/interface"
import dayjs from "dayjs"
import { ChangeEventHandler, useCallback, useState } from "react"
import { Helmet } from "react-helmet"
import styled from "styled-components"
import { calcResult, ExportExcel, formatFileStr, getTxtStr, readXLSX, TXLSXResult } from "./utils"

enum OperateState {
  idle,
  operate,
  done
}

function SettlementSheet() {
  const [selectFileList, setSelectFileList] = useState<UploadFile<any>[]>([])
  const [operateState, setOperateState] = useState(OperateState.idle)
  const [addonFileList, setAddonFileList] = useState<UploadFile<any>[]>([])
  const [downloadData, setDownloadData] = useState<{
    name: string;
    fileName: string;
    companyName: string;
    data: {
      code: string;
      fee: number;
      exchangePercent: string;
      exchange: number;
      coPercent: string;
      actualsum: number;
    }[]
  }[]>([])
  const [fileName, setFileName] = useState("结算单_" + dayjs().format("YYYY-MM-DD"))
  const [operatingSteps, setOperatingSteps] = useState("")

  const handleSelectFileList = useCallback<(info: UploadChangeParam) => any>(info => {
    setSelectFileList(old => {
      if (old.length > info.fileList.length) {
        // 删除
        return info.fileList
      } else if (old.findIndex(file => file.name === info.file.name) === -1) {
        // 添加新项
        setOperateState(OperateState.idle)
        return [...old, info.file]
      }
      return old
    })
  }, [])

  const handleAddonFile = useCallback<(info: UploadChangeParam) => any>(async (info) => {
    console.log(await readXLSX(info.file as any))
    setAddonFileList(old => {
      if (old.length > info.fileList.length) {
        // 删除
        return info.fileList
      } else if (old.findIndex(file => file.name === info.file.name) === -1) {
        // 添加新项
        setOperateState(OperateState.idle)
        return [...old, info.file]
      }
      return old
    })
  }, [])

  const changeFileName = useCallback<ChangeEventHandler<HTMLInputElement>>((str) => {
    setFileName(str.target.value)
  }, [])

  const handleFiles = useCallback(async () => {
    if (!fileName) {
      setOperatingSteps("文件名不能为空")
      return
    }
    if (!selectFileList.length) {
      setOperatingSteps("未选择文件")
      return
    }
    setOperateState(OperateState.operate)
    try {
      // 格式化交返比例文件
      const exchangePercent: { [key: string]: TXLSXResult } = {}
      for (let index = 0; index < addonFileList.length; index++) {
        const file = addonFileList[index];
        setOperatingSteps(`读取交返比例文件：${file.name}`)
        const obj = await readXLSX(file as any)
        exchangePercent[obj.companyName] = obj
        if (typeof obj.percent !== "number" || Object.values(obj.data).filter(e => typeof e !== "number").length) {
          notification.open({
            message: '交返比例异常',
            description: `文件：${file.name} 包含错误比例数据`,
            duration: 0,
          });
        }
      }
      // 格式化数据文件
      const fmtedFileList = []
      for (let index = 0; index < selectFileList.length; index++) {
        const file = selectFileList[index];
        setOperatingSteps(`读取数据文件：${file.name} 并计算`)
        const str = await getTxtStr(file);
        const result = formatFileStr(str);
        if (result) {
          // 根据数据文件中的期货公司名称找到交返比例文件相同公司获取数据
          const exchgFile = exchangePercent[result.conpanyName]
          if (exchgFile) {
            const calced = calcResult(result, exchgFile)
            fmtedFileList.push({
              name: result.clientName,
              fileName: file.name,
              companyName: result.conpanyName,
              data: calced
            })
            setDownloadData(fmtedFileList)
          } else {
            console.log(`未找到 ${file.name} 对应交返比例文件`);
            setOperatingSteps(`未找到 ${file.name} 对应交返比例文件`)
            notification.open({
              message: '交返比例异常',
              description: `未找到 ${file.name} 对应交返比例文件`,
              duration: 0,
            });
          }
        } else {
          console.log(`未能提取：${file.name} 有效数据`);
          setOperatingSteps(`未能提取：${file.name} 有效数据`)
          notification.open({
            message: '数据异常',
            description: `未能提取：${file.name} 有效数据`,
            duration: 0,
          });
        }
      }
      setOperatingSteps(`文件全部读取完成`)
      setOperateState(OperateState.done)
    } catch (error) {
      console.log(error);
      setOperatingSteps(`错误：${error}`)
      setOperateState(OperateState.done)
    }
  }, [addonFileList, fileName, selectFileList])

  const saveFile = useCallback(() => {
    setOperatingSteps(`开始处理文件`)
    if (downloadData.length) {
      const excel = new ExportExcel()
      downloadData.forEach(ele => {
        setOperatingSteps(`生成Excel Sheet：${ele.fileName}`)
        const data = ele.data.slice()
        const fee = data.map(e => e.fee)
        const exchange = data.map(e => e.exchange)
        const actualsum = data.map(e => e.actualsum)
        data.push({
          code: "总计",
          fee: parseFloat(fee.reduce((x, y) => x + y).toFixed(2)),
          exchangePercent: "",
          exchange: parseFloat(exchange.reduce((x, y) => x + y).toFixed(2)),
          coPercent: "",
          actualsum: parseFloat(actualsum.reduce((x, y) => x + y).toFixed(2)),
        })
        excel.add(data, ["品种", "手续费", "交返比例", "交返金额", "期货公司比例", "实际金额"])
      })
      excel.save(fileName, downloadData.map(e => e.fileName))
      setOperatingSteps(`完成，共计输出${downloadData.length}张表`)
    }
  }, [downloadData, fileName])

  return <Container>
    <Helmet>
      <title>结算单统计</title>
    </Helmet>
    <Upload disabled={operateState === OperateState.operate} fileList={selectFileList} onChange={handleSelectFileList} accept=".txt" beforeUpload={() => false} multiple>
      <Button disabled={operateState === OperateState.operate} type="primary">选择待处理文件</Button>
      <Button onClick={() => setSelectFileList([])}><DeleteOutlined /></Button>
    </Upload>
    <br />
    <Upload disabled={operateState === OperateState.operate} fileList={addonFileList} onChange={handleAddonFile} accept=".xls,.xlsx" beforeUpload={() => false} multiple>
      <Button disabled={operateState === OperateState.operate} type="primary">选择交返比例文件</Button>
      <Button onClick={() => setAddonFileList([])}><DeleteOutlined /></Button>
    </Upload>
    <Divider></Divider>
    <FileMsgWrapper>
      <Input addonBefore="输出文件名" addonAfter=".xlsx" value={fileName} onChange={changeFileName} />
    </FileMsgWrapper>
    <Button type="primary" loading={operateState === OperateState.operate} disabled={operateState === OperateState.operate} onClick={handleFiles}>
      {operateState === OperateState.operate ? "处理中" : "读取并计算"}
    </Button>
    <Button disabled={!downloadData.length} type="link" onClick={saveFile}>下载</Button>
    <OperateMsg>{operatingSteps}</OperateMsg>
  </Container>
}
const Container = styled.div`
  padding: 15px;
  .ant-upload-list.ant-upload-list-text {
    display: flex;
    flex-wrap: wrap;
  }
`

const FileMsgWrapper = styled.div`
  display: flex;
  margin-bottom: 15px;
  .ant-input-group-wrapper {
    margin-right: 15px;
    flex: none;
    width: 300px;
  }
`

const OperateMsg = styled.span`
  color: #999;
`

export default SettlementSheet
